<script lang="tsx">
  import { VxeFormInstance } from 'vxe-table';
  import { FormPropsVxe } from '@/components/BasicVxeForm/useVxeForm';
  import { omit, set, get, cloneDeep, isArray, isFunction } from 'lodash-es';
  import { unref } from 'vue';
  import { deepMerge } from '@/utils';
  import { warn } from '@/utils/log';

  export default defineComponent({
    // ！废弃 组件标签属性传递 使用 hooks 方法形参替代
    // inheritAttrs: true,
    // props: {
    //   onReset: {
    //     type: Function as PropType<VxeFormEvents.Reset>,
    //     default: noop,
    //   },
    //   onCollapse: {
    //     type: Function as PropType<VxeFormEvents.Collapse>,
    //     default: noop,
    //   },
    //   onSubmit: {
    //     type: Function as PropType<VxeFormEvents.Submit>,
    //     default: noop,
    //   },
    //   onSubmitInvalid: {
    //     type: Function as PropType<VxeFormEvents.SubmitInvalid>,
    //     default: noop,
    //   },
    // },
    emits: ['register', 'collapse', 'toggle-collapse', 'submit', 'submit-invalid', 'reset'],
    setup(_, { emit, slots }) {
      const $formRef = ref<VxeFormInstance>();
      const propsRef: Ref<Partial<FormPropsVxe>> = ref({});
      const setProps = async (props: FormPropsVxe) => {
        propsRef.value = deepMerge(unref(propsRef) || ({} as any), props);
        Object.keys(props).map((key) => {
          set(propsRef.value, key, props[key]);
        });
      };
      const setPropField = async (prop: string, value: any) => {
        set(propsRef.value, prop, value);
      };

      const getPropField = (prop: string): any => {
        return get(unref(propsRef), prop);
      };

      const getProps = (): FormPropsVxe => {
        return unref(propsRef) as FormPropsVxe;
      };

      // 重写onSubmit
      const onSubmit = async () => {
        const formData = cloneDeep(propsRef.value?.formData ?? {});
        // 统一填补 空数据 null or undefined
        (propsRef.value?.items || []).map((item) => {
          if (item.field && [undefined, null].includes(formData[item.field])) {
            set(formData, item.field, null);
          }
        });
        warn(JSON.stringify(formData, null, 4));
        const t: any = { formData, $form: unref($formRef), propsRef: unref(propsRef) };
        if (isFunction(propsRef.value.onSubmit)) {
          propsRef.value.onSubmit(t);
        } else {
          emit('submit', t);
        }
      };

      const rulesAll = computed(() => {
        const itemsRules = (propsRef.value?.items ?? [])
          .filter((e) => typeof e.field === 'string' && isArray(e.rules))
          .map((e) => ({ [e.field as string]: e.rules }));
        const _rules = cloneDeep(propsRef.value?.rules || {});
        return {
          ..._rules,
          ...Object.assign({}, ...itemsRules),
        };
      });

      // 注册
      onMounted(async () => {
        const methods = {
          // ...unref($formRef),
          // $form: $formRef,
          setProps,
          setPropField,
          getPropField,
          getProps,
          onSubmit,
          getRulesAll() {
            return unref(rulesAll);
          },
        };
        // 重写的方法排除 继承formMethods原有成员方法
        [
          'getRefMaps',
          'getComputeMaps',
          'dispatchEvent',
          'reset',
          'validate',
          'validateField',
          'clearValidate',
          'updateStatus',
          'toggleCollapse',
          'getItems',
          'getItemByField',
          'closeTooltip',
          'callSlot',
          'triggerItemEvent',
          'toggleCollapseEvent',
          'triggerTitleTipEvent',
          'handleTitleTipLeaveEvent',
          'onSubmit',
          'getRulesAll',
        ].map((fnKey) => {
          if (!methods[fnKey]) {
            methods[fnKey] = (...args) => {
              const form = $formRef.value;
              console.log(form?.[fnKey], fnKey, args);
              return form?.[fnKey](...args);
            };
          }
        });
        emit('register', methods, function (_propsRef: FormPropsVxe) {
          propsRef.value = _propsRef;
        });
      });
      // return () => (
      //   <vxe-form
      //     ref={$formRef}
      //     {...omit(propsRef.value, ['data', 'formData', 'rules', 'onSubmit'])}
      //     onSubmit={onSubmit}
      //     rules={rulesAll.value}
      //     data={propsRef.value?.formData ?? {}}
      //     v-slots={slots}
      //   ></vxe-form>
      // );

      return {
        $formRef,
        onSubmit,
        rulesAll,
        propsRef,
        omit,
      };
    },
  });
</script>
<template>
  <vxe-form
    ref="$formRef"
    v-bind="omit(propsRef, ['data', 'formData', 'rules', 'onSubmit'])"
    @submit="onSubmit"
    :rules="rulesAll"
    :data="propsRef?.formData ?? {}"
  >
    <template #[key]="slotData" v-for="key in Object.keys($slots)">
      <slot :name="key" v-bind="slotData ? { ...slotData } : {}"></slot>
    </template>
  </vxe-form>
</template>
<style scoped lang="scss"></style>
